from sqlalchemy import select, insert
from sqlalchemy.orm import selectinload
from streamlit_authenticator.utilities.hasher import Hasher
from database.engine import get_session_factory
from database.models.base import Sex
from database.models.user import User
from database.models.weight_update import WeightUpdate


class SynOrmUserQueries:
    @staticmethod
    def get_users():
        with get_session_factory()() as session:
            query = (
                select(User)
                .options(selectinload(User.products))
            )
            
            result_iterator = session.execute(query)
            result = result_iterator.scalars().all()
            
            return result
    
    
    @staticmethod
    def test_insert_users():
        with get_session_factory()() as session:
            query = (
                insert(User)
                .values(
                    [
                        {
                            "username": "boba",
                            "password_hash": Hasher(["11"]).generate()[0],
                            "name": "aboba",
                            "birth": "2002-01-01",
                            "weight": 34,
                            "height": 155,
                            "sex": Sex["Мужчина"],
                            "purpose_name": "Похудеть",
                            "physical_activity_name": 
                                "Минимум/отсутствие физической нагрузки",
                        },
                        {
                            "username": "aboba",
                            "password_hash": Hasher(["12"]).generate()[0],
                            "name": "aboba",
                            "birth": "2001-01-01",
                            "weight": 24,
                            "height": 155,
                            "sex": Sex["Мужчина"],
                            "purpose_name": "Держать вес",
                            "physical_activity_name": 
                                "Тренировки 3-4 раза в неделю",
                        },
                        {
                            "username": "eboba",
                            "password_hash": Hasher(["13"]).generate()[0],
                            "name": "aboba",
                            "birth": "2003-01-01",
                            "weight": 34,
                            "height": 165,
                            "sex": Sex["Женщина"],
                            "purpose_name": "Похудеть",
                            "physical_activity_name": "Тренировки каждый день",
                        },
                        {
                            "username": "fboba",
                            "password_hash": Hasher(["14"]).generate()[0],
                            "name": "aboba",
                            "birth": "2003-01-01",
                            "weight": 54,
                            "height": 175,
                            "sex": Sex["Женщина"],
                            "purpose_name": "Набрать вес",
                            "physical_activity_name": "2 тренировки в день",
                        },
                    ]
                )
            )
            session.execute(query)
            session.commit()
                
                
    @staticmethod
    def get_user_password_hash(username: str) -> str | None:
        with get_session_factory()() as session:
            query = select(User.password_hash).where(User.username == username)
            result_iterator = session.execute(query)
            user_password_hash = result_iterator.scalars().one_or_none()
            return user_password_hash
    
    
    @staticmethod
    def check_username_unique(username: str) -> bool:
        with get_session_factory()() as session:
            query = select(User.username).where(User.username == username)
            result_iterator = session.execute(query)
            existing_username = result_iterator.scalars().one_or_none()
            return existing_username is None
        
        
    @staticmethod
    def get_user_by_username(username: str)  -> User | None:
        with get_session_factory()() as session:
            query = (
                select(User)
                .where(User.username == username)
                .options(
                    selectinload(User.products),
                    selectinload(User.purpose),
                    selectinload(User.physical_activity),
                    selectinload(User.weight_updates)
                )
            )
            result_iterator = session.execute(query)
            user = result_iterator.scalars().one_or_none()
            return user
            
            
    @staticmethod
    def signup_user(**kwargs) -> bool:
        with get_session_factory()() as session:
            user = User(**kwargs)
            session.add(user)
            session.commit()
            session.add(WeightUpdate(username=user.username, weight=user.weight))
            session.commit()
        return __class__.get_user_by_username(kwargs["username"])
    
    
    @staticmethod
    def update_user(**kwargs) -> bool:
        with get_session_factory()() as session:
            user = None
            if "username" in kwargs:
                query = select(User).where(User.username == kwargs["username"])
                result_iterator = session.execute(query)
                user = result_iterator.scalars().one_or_none()
            if user:
                for key, value in kwargs.items():
                    if key != "username":
                        setattr(user, key, value)
                session.add(WeightUpdate(username=user.username, weight=user.weight))
                session.commit()
            return user
            